package com.zx.system.block.service.impl;

import com.zx.core.enums.StatusEnum;
import com.zx.core.wrapper.ListWrapper;
import com.zx.core.wrapper.ObjectWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.security.block.uitls.SecurityUtils;
import com.zx.system.block.dao.SysMenuMapper;
import com.zx.system.block.dao.SysRoleMapper;
import com.zx.system.block.dao.SysRoleMenuMapper;
import com.zx.system.block.dao.SysUserRoleMapper;
import com.zx.system.block.mapstruct.RoleMapStructMapper;
import com.zx.system.block.model.SysMenu;
import com.zx.system.block.model.SysRole;
import com.zx.system.block.model.SysRoleMenu;
import com.zx.system.block.model.SysUserRole;
import com.zx.system.block.param.RoleParam;
import com.zx.system.block.service.ISysRoleService;
import com.zx.system.block.utils.SystemNoUtils;
import com.zx.system.block.vo.SysRoleVO;
import com.zx.validation.annotation.ParameterValidation;
import com.zx.validation.annotation.ParameterValidations;
import com.zx.validation.enums.ValidateRulesEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * description: 业务层角色服务实现 <br>
 * create: 2024-08-24 11:57
 * </p>
 *
 * @author zhou  xun
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements ISysRoleService {
    private final SysRoleMapper sysRoleMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysRoleMenuMapper sysRoleMenuMapper;
    private final SysMenuMapper sysMenuMapper;

    /**
     * 获取角色信息Map 用于角色信息匹配
     *
     * @return 包含角色标识符作为键, {@link SysRole} 对象作为值的映射表{@code Map<String, SysRole>}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public Map<String, SysRole> getRole() {
        Map<String, SysRole> map = new HashMap<>();
        List<SysRole> sysRoleList = sysRoleMapper.selectRoleList(null);
        if (null != sysRoleList && !sysRoleList.isEmpty()) {
            //将列表转换为 Map
            for (SysRole sysRole : sysRoleList) {
                map.putIfAbsent(sysRole.getId(), sysRole);
            }
        }
        return map;
    }

    /**
     * 查询角色列表
     *
     * @param roleParam 角色参数
     * @return {@link ListWrapper<SysRole>}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ListWrapper<SysRole> selectRoleList(RoleParam roleParam) {
        ListWrapper<SysRole> result = new ListWrapper<>();
        try {
            SysRole sysRole = RoleMapStructMapper.INSTANCE.roleParamToSysRole(roleParam);
            List<SysRole> sysRoleList = sysRoleMapper.selectRoleList(sysRole);
            if (null != sysRoleList && !sysRoleList.isEmpty()) {
                result.setData(sysRoleList);
            }
        } catch (Exception e) {
            log.error("查询角色列表时发生错误", e);
            result.fail("查询角色列表时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 新增角色
     *
     * @param roleParam 角色参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */

    @Override
    public ResponseWrapper addRole(RoleParam roleParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            List<SysRole> checkNameList = sysRoleMapper.selectRoleList(SysRole.builder()
                    .name(roleParam.getName())
                    .build());
            if (null != checkNameList && !checkNameList.isEmpty()) {
                if (checkNameList.stream().anyMatch(role -> role.getName().equals(roleParam.getName()))) {
                    result.fail("已存在相同角色名称!");
                    return result;
                }
            }
            List<SysRole> checkRoleKeyList = sysRoleMapper.selectRoleList(SysRole.builder()
                    .roleKey(roleParam.getRoleKey())
                    .build());
            if (null != checkRoleKeyList && !checkRoleKeyList.isEmpty()) {
                if (checkRoleKeyList.stream().anyMatch(role -> role.getRoleKey().equals(roleParam.getRoleKey()))) {
                    result.fail("已存在相同角色标识符!");
                    return result;
                }
            }
            // 验证角色状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(roleParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的角色状态错误!");
                return result;
            }
            SysRole sysRole = RoleMapStructMapper.INSTANCE.roleParamToSysRole(roleParam);
            // 设置id
            sysRole.setId(SystemNoUtils.generateSystemId());
            sysRole.setCreateBy(SecurityUtils.getUserId());
            sysRole.setCreateTime(LocalDateTime.now());
            sysRoleMapper.insert(sysRole);
        } catch (Exception e) {
            log.error("新增角色时发生错误", e);
            result.fail("新增角色时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑角色
     *
     * @param roleParam 角色参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */

    @Override
    public ResponseWrapper editRole(RoleParam roleParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            List<SysRole> sysRoleList = sysRoleMapper.selectRoleList(SysRole.builder()
                    .name(roleParam.getName())
                    .build());
            if (null != sysRoleList && !sysRoleList.isEmpty()) {
                if (sysRoleList.stream().anyMatch(role -> role.getName().equals(roleParam.getName())
                        && !role.getId().equals(roleParam.getId()))) {
                    result.fail("已存在相同角色名称!");
                    return result;
                }
            }
            // 验证角色状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(roleParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的角色状态错误!");
                return result;
            }
            SysRole sysRole = RoleMapStructMapper.INSTANCE.roleParamToSysRole(roleParam);
            sysRole.setUpdateBy(SecurityUtils.getUserId());
            sysRole.setUpdateTime(LocalDateTime.now());
            sysRoleMapper.updateByPrimaryKeySelective(sysRole);
        } catch (Exception e) {
            log.error("编辑角色时发生错误", e);
            result.fail("编辑角色时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑角色状态
     *
     * @param id     角色Id
     * @param status 角色状态 0停用 1 启用
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */

    @Override
    public ResponseWrapper editRoleStatus(String id, Integer status) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证角色状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(status);
            if (null == statusEnum) {
                result.fail("传入的角色状态错误!");
                return result;
            }
            // 验证角色是否存在
            SysRole selectByPrimaryKey = sysRoleMapper.selectByPrimaryKey(id);
            if (null == selectByPrimaryKey) {
                result.fail("传入的角色信息不存在!");
                return result;
            }
            SysRole sysRole = new SysRole();
            sysRole.setId(id);
            sysRole.setStatus(status);
            sysRole.setUpdateBy(SecurityUtils.getUserId());
            sysRole.setUpdateTime(LocalDateTime.now());
            sysRoleMapper.updateByPrimaryKeySelective(sysRole);
        } catch (Exception e) {
            log.error("编辑角色状态时发生错误", e);
            result.fail("编辑角色状态时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 删除角色
     *
     * @param roleId 角色Id
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ResponseWrapper deleteRole(String roleId) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证角色是否存在
            SysRole selectByPrimaryKey = sysRoleMapper.selectByPrimaryKey(roleId);
            if (null == selectByPrimaryKey) {
                result.fail("传入的角色信息不存在!");
                return result;
            }
            //验证是否存在用户关联了角色
            List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectUserRoleByRoleId(roleId);
            if (sysUserRoleList != null && !sysUserRoleList.isEmpty()) {
                result.fail("该角色已分配给用户，无法删除!");
                return result;
            }
            //验证是否存在角色是否管理了菜单
            List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectRoleMenuByRoleId(roleId);
            if (sysRoleMenuList != null && !sysRoleMenuList.isEmpty()) {
                result.fail("该角色已分配菜单，无法删除!");
                return result;
            }
            sysRoleMapper.deleteByPrimaryKey(roleId);
        } catch (Exception e) {
            log.error("删除角色时发生错误", e);
            result.fail("删除角色时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 角色设置权限
     *
     * @param roleId  角色Id
     * @param menuIds 菜单Id列表
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @ParameterValidations({
            @ParameterValidation(index = 0, desc = "角色Id", rules = {ValidateRulesEnum.NOT_NULL}),
    })
    @Override
    public ResponseWrapper roleSetMenu(String roleId, String[] menuIds) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证角色是否存在
            SysRole selectByPrimaryKey = sysRoleMapper.selectByPrimaryKey(roleId);
            if (null == selectByPrimaryKey) {
                result.fail("传入的角色信息不存在!");
                return result;
            }
            //查询菜单列表验证菜单id是否正确
            List<SysMenu> sysMenus = sysMenuMapper.selectSysMenuList(null);
            List<String> idlist = sysMenus.stream().map(SysMenu::getId).toList();
            if (!Arrays.asList(menuIds).isEmpty()) {
                for (String menuId : menuIds) {
                    if (!idlist.contains(menuId)) {
                        result.fail("传入的菜单信息不存在!");
                        return result;
                    }
                }
                List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectRoleMenuByRoleId(roleId);
                List<String> checkList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).toList();
                List<String> addList = new ArrayList<>();
                List<String> deleteList = new ArrayList<>();
                for (String menuId : menuIds) {
                    if (!checkList.contains(menuId)) {
                        addList.add(menuId);
                    }
                }
                for (String menuId : checkList) {
                    if (!Arrays.asList(menuIds).contains(menuId)) {
                        deleteList.add(menuId);
                    }
                }
                if (!addList.isEmpty()) {
                    List<SysRoleMenu> sysRoleMenuList1 = addList.stream().map(menuId -> new SysRoleMenu(roleId, menuId)).toList();
                    sysRoleMenuMapper.batchInsert(sysRoleMenuList1);
                }
                if (!deleteList.isEmpty()) {
                    sysRoleMenuMapper.batchDeleteByRoleIdAndMenuIds(roleId, deleteList);
                }
            } else {
                sysRoleMenuMapper.deleteByRoleId(roleId);
            }
        } catch (Exception e) {
            log.error("删除角色时发生错误", e);
            result.fail("删除角色时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 查询角色的菜单id列表
     *
     * @param roleId 角色Id
     * @return {@link Set<String>} 菜单id集合
     * @author zhou  xun
     * @since 2025-04-15
     */
    @Override
    public ObjectWrapper<Set<String>> selectMenuIdsByRoleId(String roleId) {
        ObjectWrapper<Set<String>> result = new ObjectWrapper<>();
        try {
            List<SysMenu> sysMenuList = sysMenuMapper.selectMenuIdsByRoleId(roleId);
            if (null != sysMenuList && !sysMenuList.isEmpty()) {
                Set<String> menuIdSet = sysMenuList.stream()
                        .filter(sysRole -> StatusEnum.ENABLE.getCode().equals(sysRole.getStatus()))
                        .map(SysMenu::getId)
                        .collect(Collectors.toSet());
                if (!menuIdSet.isEmpty()) {
                    result.setData(menuIdSet);
                }
            }
        } catch (Exception e) {
            log.error("查询角色的菜单id列表时发生错误", e);
            result.fail("查询角色的菜单id列表时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 查询角色信息
     *
     * @param userId 用户id
     * @return {@link  ListWrapper<SysRole> } 角色集合
     * @author zhou  xun
     * @since 2025-04-17
     */
    @Override
    public ListWrapper<SysRole> selectRoleInfos(String userId) {
        ListWrapper<SysRole> result = new ListWrapper<>();
        try {
            List<SysRole> sysRoleList = sysRoleMapper.selectRoleByUserId(userId);
            if (!sysRoleList.isEmpty()) {
                result.setData(sysRoleList);
            }
        } catch (Exception e) {
            log.error("查询角色信息时发生错误", e);
            result.fail("查询角色信息时发生错误: " + e.getMessage());
        }
        return result;
    }

    @Override
    public ListWrapper<SysRoleVO> selectRoleVOList(RoleParam roleParam) {
        // 获取角色列表
        ListWrapper<SysRole> listWrapper = selectRoleList(roleParam);

        // 验证请求是否成功
        if (listWrapper.verifyFail()) {
            ListWrapper<SysRoleVO> result = new ListWrapper<>();
            result.fail(listWrapper.getMsg());
            return result;
        }
        ListWrapper<SysRoleVO> result = new ListWrapper<>();
        if (null != listWrapper.getData() && !listWrapper.getData().isEmpty()) {
            // 转换并处理数据
            List<SysRoleVO> processedData = listWrapper.getData().stream()
                    .map(RoleMapStructMapper.INSTANCE::sysRoleToSysRoleVO)
                    .collect(Collectors.toList());
            result.setData(processedData);
        }
        return result;
    }
}
